﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UBlockly.Scriptable;
using UnityEditor;
using UBlockly.UI;
using System.Threading.Tasks;
using UBlockly.Compotent;
using UBlockly.Util;

public static class BaseBlockMaker
{
    [MenuItem("BlockTool/生成基础block块")]
    public static void BuildBaseTypeBlock()
    {
        var list = UTool.TryParse<CodingDefineMono>();
        list.ForEach(assist => {
            CreateNormalBlock(assist);
        });
    }

    [MenuItem("BlockTool/生成条件block块")]
    public static void BuildConditionTypeBlock()
    {

    }
    
    [MenuItem("BlockTool/拷贝到工程目录")]
    public static void ddddd()
    {

    }

    public static void CreateNormalBlock(FunctionBlockAssist funcAssist)
    {
        var func = FunctionFactory.CreateILFunc(funcAssist.GetFuncType());
        RectTransform block = null;
        if (func.ResultType == ILFunResult.VoidR)
        {
            block = CreateBlock<SlotTypeBlock>(funcAssist.GetFuncName());
        }
        else
        {
            block = CreateBlock<PackTypeBlock>(funcAssist.GetFuncName());
        }
        RectTransform desc = CreateDesc(block.transform, funcAssist.FunctionDesc);
        RectTransform packinfo = CreatePackInfos(block, func.ParamType, null);
        RectTransform slotInfo = null;
        if (func.ResultType == ILFunResult.VoidR)
        {
            slotInfo = CreateSlotInfos(block, 2);
        }

        var assist = block.gameObject.AddComponent<NodeConfigAssist>();
        assist.FunctionName = funcAssist.GetFuncName();
        assist.FuncType = funcAssist.GetFuncType();
        if (packinfo != null && packinfo.transform.childCount != 0)
        {
            assist.ParamTransform = packinfo.transform;
            assist.Packs = new Transform[1];
            assist.Packs[0] = packinfo.transform;
        }
        if (slotInfo != null && slotInfo.childCount != 0)
        {
            if (slotInfo.transform.childCount % 2 == 0)
            {
                assist.Slots = new Transform[slotInfo.transform.childCount];
                for (int i = 0; i < slotInfo.transform.childCount; i++)
                {
                    assist.Slots[i] = slotInfo.transform.GetChild(i);
                }
            }
            else
            {
                Debug.LogError("slot info 必须成对出现");
            }
        }
        SetLayout(func.ParamType, func.ResultType, block, desc, packinfo, slotInfo);
        SetColor(func.ParamType, func.ResultType, block, desc, packinfo);
        SetSprite(block, funcAssist.GetFuncType(), funcAssist.FunctionDefineStr);

        string path = string.Format("{0}/BlockAssets/GeneratorBlocks/{1}.{2}", Application.dataPath, assist.FunctionName, "prefab");
        if (System.IO.File.Exists(path))
            System.IO.File.Delete(path);
        PrefabUtility.SaveAsPrefabAsset(block.gameObject, path);
        GameObject.DestroyImmediate(block.gameObject);
    }

    public static RectTransform CreateBlock<T>(string blockName) where T:BlockObject
    {
        BlockObject block = new GameObject(blockName).AddComponent<T>();
        var image = block.gameObject.AddComponent<UImage>();
        var recttrans = block.GetComponent<RectTransform>();
        recttrans.anchorMin = new Vector2(0, 1);
        recttrans.anchorMax = new Vector2(0, 1);
        recttrans.pivot = new Vector2(0, 1);
        return block.BlockAnchor.RectTransform;
    }

    public static RectTransform CreateDesc(Transform block, string text)
    {
        var desc = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/BlockAssets/UCompotents/Desc.prefab");
        desc = GameObject.Instantiate(desc, block);
        desc.name = "Desc";
        desc.GetComponent<UText>().text = text;
        var recttrans = desc.GetComponent<RectTransform>();
        recttrans.anchorMin = new Vector2(0, 0.5f);
        recttrans.anchorMax = new Vector2(0, 0.5f);
        recttrans.pivot = new Vector2(0, 0.5f);
        recttrans.anchoredPosition = Vector2.zero;
        return desc.GetComponent<RectTransform>();
    }

    public static void SetLayout(ILFunResult paramType, ILFunResult resultType, RectTransform block, RectTransform desc, RectTransform pack, RectTransform slot)
    {
        var text = desc.GetComponent<UText>();
        text.fontSize = BSize.DescFontSize;
        int yoffset = resultType == ILFunResult.VoidR ? (BSize.PackParamDownSpace - BSize.PackParamUpSpace) / 2 : 0;
                      int len = Common.GetFontLen(text.font, BSize.DescFontSize, text.text);
        desc.sizeDelta = new Vector2(len, BSize.DescHeight);
        desc.anchoredPosition = new Vector2(BSize.DescLeftBorder, yoffset);
        len += (BSize.DescLeftBorder + BSize.DescRightBorder);
        int blockHeight = resultType == ILFunResult.VoidR ? BSize.VoidNodeHeight : BSize.NVoidNodeHeight;
        if (paramType != ILFunResult.VoidR)
        {
            var plen = 0;
            if (paramType == ILFunResult.BoolR)
            {
                plen = BSize.PackParamLen_Bool;
            }
            else if (paramType == ILFunResult.IntR)
            {
                plen = BSize.PackParamLen_Int;
            }
            else if (paramType == ILFunResult.StringR)
            {
                plen = BSize.PackParamLen_String;
            }
            if (pack != null)
            {
                var updownspace = resultType == ILFunResult.VoidR
                    ? BSize.PackParamUpSpace + BSize.PackParamDownSpace
                    : BSize.PackParamUpSpace * 2;
                   pack.sizeDelta = new Vector2(plen + BSize.PackParamBorder*2,blockHeight - updownspace);
                pack.anchoredPosition = new Vector2(len, yoffset);
                if (pack.GetChild(0) != null)
                {
                    var paramNode = pack.GetChild(0).GetComponent<RectTransform>();
                    paramNode.anchoredPosition = new Vector2(BSize.PackParamBorder,0);
                    paramNode.sizeDelta = new Vector2(plen,pack.sizeDelta.y - 2*BSize.PackParamBorder);
                }
            }
            len += (int)(pack.sizeDelta.x + BSize.PackParamRightSpace);
        }
        block.sizeDelta = new Vector2(len, blockHeight);
    }

    public static void SetColor(ILFunResult paramType, ILFunResult resultType, RectTransform block, RectTransform desc, RectTransform pack)
    {
        var packColor = Color.white;
        var packNodeColor = Color.white;
        var descColor = Color.black;
        var blockColor = Color.white;
        var inputTextColor = Color.white;
        if (paramType != ILFunResult.VoidR)
        {
            if (paramType == ILFunResult.BoolR)
            {
                packColor = BSize.PackParam_BoolColor;
            }
            else if (paramType == ILFunResult.IntR)
            {
                packColor = BSize.PackParam_IntColor;
            }
            else if (paramType == ILFunResult.StringR)
            {
                packColor = BSize.PackParam_StringColor;
            }
        }
        if (resultType == ILFunResult.VoidR)
            blockColor = BSize.VoidTypeNodeColor;
        else if (resultType == ILFunResult.BoolR)
            blockColor = BSize.BoolTypeNodeColor;
        else if (resultType == ILFunResult.IntR)
            blockColor = BSize.IntTypeNodeColor;
        else if (resultType == ILFunResult.StringR)
            blockColor = BSize.StringTypeNodeColor;
        if (pack != null && pack.GetComponent<UImage>() != null)
            pack.GetComponent<UImage>().color = packColor;
        if (desc != null && desc.GetComponent<UText>() != null)
            desc.GetComponent<UText>().color = descColor;
        block.GetComponent<UImage>().color = blockColor;
    }

    public static void SetSprite(RectTransform block, string spriteName)
    {
        var sp = AssetDatabase.LoadAssetAtPath<Sprite>(string.Format("Assets/BlockAssets/Sprites/{0}.{1}", spriteName, "png"));
        block.GetComponent<UImage>().sprite = sp;
        block.GetComponent<UImage>().type = UnityEngine.UI.Image.Type.Sliced;
    }

    public static RectTransform CreatePackInfos(RectTransform block, ILFunResult paramType, ConbomParam[] defaultParams = null)
    {
        GameObject paramCompotent = null;
        switch (paramType)
        {
            case ILFunResult.None:
                break;
            case ILFunResult.BoolR:
                paramCompotent = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/BlockAssets/UCompotents/UBoolInputCompotent.prefab");
                break;
            case ILFunResult.IntR:
                paramCompotent = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/BlockAssets/UCompotents/UIntInputCompotent.prefab");
                break;
            case ILFunResult.StringR:
                paramCompotent = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/BlockAssets/UCompotents/UStringInputCompotent.prefab");
                break;
            case ILFunResult.VoidR:
                if (defaultParams != null)   //下拉框类型的
                {
                    paramCompotent = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/RawRes/Blocks/UCompotents/UDropInputCompotent.prefab");
                }
                break;
        }
        if (paramCompotent != null)
        {
            var recttrans = new GameObject("PackInfo").AddComponent<BlockAnchor>().RectTransform;
            recttrans.SetParent(block);
            recttrans.anchorMin = new Vector2(0, 0.5f);
            recttrans.anchorMax = new Vector2(0, 0.5f);
            recttrans.pivot = new Vector2(0, 0.5f);
            recttrans.gameObject.AddComponent<UImage>();
            paramCompotent = GameObject.Instantiate(paramCompotent);
            paramCompotent.transform.SetParent(recttrans);
            var rt = paramCompotent.GetComponent<RectTransform>();
            rt.anchorMin = new Vector2(0, 0.5f);
            rt.anchorMax = new Vector2(0, 0.5f);
            rt.pivot = new Vector2(0, 0.5f);
//            rt.offsetMin = Vector2.one * BSize.PackParamBorder;
//            rt.offsetMax = -Vector2.one * BSize.PackParamBorder;
            var input = paramCompotent.GetComponent<UInputField>();
            if (input != null)
            {
                input.textComponent.fontSize = BSize.InputComponentFontSize;
                input.placeholder.GetComponent<UnityEngine.UI.Text>().fontSize = BSize.InputComponentFontSize;
            }
            return recttrans;
        }
        return null;
    }

    public static RectTransform CreateSlotInfos(RectTransform block, int count = 2)
    {
        if (count == 0)
            return null;
        RectTransform slotInfo = new GameObject("SlotInfo").AddComponent<RectTransform>();
        slotInfo.SetParent(block);
        slotInfo.anchorMin = Vector2.zero;
        slotInfo.anchorMax = Vector2.one;
        slotInfo.offsetMin = Vector2.zero;
        slotInfo.offsetMax = Vector2.zero;
        RectTransform recttrans = null;
        GameObject upsoltInfo = new GameObject("SlotInfo-Upper");
        upsoltInfo.transform.SetParent(slotInfo.transform);
        if (count == 2)
        {
            recttrans = upsoltInfo.AddComponent<RectTransform>();
            recttrans.anchorMin = new Vector2(0, 1);
            recttrans.anchorMax = new Vector2(0, 1);
            recttrans.pivot = Vector2.zero;
            recttrans.offsetMin = Vector2.zero;
            recttrans.sizeDelta = new Vector2(120, 50);
        }
        GameObject downslotInfo = new GameObject("SlotInfo-Down");
        recttrans = downslotInfo.AddComponent<RectTransform>();
        recttrans.SetParent(slotInfo.transform);
        recttrans.anchorMin = Vector2.zero;
        recttrans.anchorMax = Vector2.zero;
        recttrans.offsetMax = Vector2.zero;
        recttrans.offsetMin = Vector2.zero;
        recttrans.pivot = new Vector2(0, 1);
        recttrans.sizeDelta = new Vector2(120, 50);
        return slotInfo;
    }

    public static void SetSprite(RectTransform normalBlock, ILFuncType functype,string funcDefineStr)
    {
        if ((uint)functype / 100 != 1)
        {
            Debug.LogError($"普通类型函数{funcDefineStr}设置sprite时创建出错，{functype.ToString()}函数类型不匹配");
            return;
        }
        var func = FunctionFactory.CreateILFunc(functype);
        string spname = BSize.VoidReturnNodeSpriteName;
        if (func.ResultType == ILFunResult.BoolR)
            spname = BSize.BoolReturnNodeSpritName;
        else if (func.ResultType == ILFunResult.IntR)
            spname = BSize.IntReturnNodeSpritName;
        else if (func.ResultType == ILFunResult.StringR)
            spname = BSize.StringReturnNodeSpritName;
        SetSprite(normalBlock, spname);
    }
}
